package com.stellar.auth.domain.authPermission.impl;

import com.stellar.auth.basic.entity.AuthPermission;
import com.stellar.auth.basic.entity.AuthRole;
import com.stellar.auth.basic.entity.AuthRolePermission;
import com.stellar.auth.basic.entity.AuthUserRole;
import com.stellar.auth.basic.service.AuthPermissionService;
import com.stellar.auth.basic.service.AuthRolePermissionService;
import com.stellar.auth.basic.service.AuthUserRoleService;
import com.stellar.auth.constants.ErrorCodeConstants;
import com.stellar.auth.controller.admin.authPermission.vo.AuthPermissionRequestPageVO;
import com.stellar.auth.controller.admin.authPermission.vo.AuthPermissionRequestVO;
import com.stellar.auth.controller.admin.authPermission.vo.AuthPermissionResponseVO;
import com.stellar.auth.controller.admin.authPermission.vo.AuthPermissionTreeVO;
import com.stellar.auth.convert.AuthPermissionConvert;
import com.stellar.auth.domain.authPermission.AuthPermissionDomainService;

import com.stellar.auth.enums.PermissionTypeEnum;
import com.stellar.core.context.LoginContextHolder;
import com.stellar.web.core.bean.PageResult;
import com.stellar.web.core.enums.IsDeletedFlagEnum;
import com.stellar.web.core.enums.IsEnabledFlagENEnum;
import com.stellar.web.core.enums.IsEnabledFlagEnum;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.stellar.core.util.ServiceExceptionUtil.exception;

/**
 * 权限表领域服务实现
 *
 * @author Jqchan
 * @version 1.0
 * @date 2025-05-16 18:07:22
 */
@Service
public class AuthPermissionDomainServiceImpl implements AuthPermissionDomainService {

    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;


    @Override
    public PageResult<AuthPermissionResponseVO> page(AuthPermissionRequestPageVO requestPageVO) {
        PageResult<AuthPermissionResponseVO> pageResult = new PageResult<>();
        AuthPermission queryEntity = AuthPermissionConvert.INSTANCE.convert(requestPageVO);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        List<AuthPermission> entities = authPermissionService.page(queryEntity,
                requestPageVO.getStart(), requestPageVO.getPageSize());

        if (entities.isEmpty()) {
            return pageResult;
        }

        Long count = authPermissionService.count(queryEntity);
        List<AuthPermissionResponseVO> vos = AuthPermissionConvert.INSTANCE.convertEntityToRespList(entities);

        pageResult.setResult(vos);
        pageResult.setTotal(count.intValue());
        return pageResult;
    }

    @Override
    public Boolean update(AuthPermissionRequestVO requestVO) {
        AuthPermission entity = AuthPermissionConvert.INSTANCE.convert(requestVO);
        return authPermissionService.update(entity) != 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Long id) {
        // 检查ID有效性
        if (id == null) {
            return false;
        }

        // 获取权限对象并校验
        AuthPermission authPermission = authPermissionService.queryById(id);
        if (authPermission == null
                || Objects.equals(authPermission.getIsDeleted(), IsDeletedFlagEnum.DELETED.getVal())) {
            return false;
        }

        // 根据类型执行不同的删除策略
        PermissionTypeEnum type = PermissionTypeEnum.getByCode(authPermission.getType());
        if (type == null) {
            return false;
        }

        switch (type) {
            case DIRECTORY:
                return deleteDirectory(authPermission);
            case MENU:
                return deleteMenu(authPermission);
            case BUTTON:
                return deleteButton(authPermission);
            default:
                return false;
        }
    }

    // 删除目录及其所有子项
    private Boolean deleteDirectory(AuthPermission directory) {
        // 递归获取所有后代节点ID
        List<Long> descendantIds = authPermissionService.findAllDescendantIds(directory.getId());

        // 添加目录自身ID
        descendantIds.add(directory.getId());

        // 批量删除权限前先删除关联关系
        deleteRolePermissionsByPermissionIds(descendantIds);

        // 批量删除所有后代节点和目录自身
        authPermissionService.batchMarkAsDeleted(descendantIds);
        return true;
    }

    // 删除菜单及其按钮
    private Boolean deleteMenu(AuthPermission menu) {
        // 获取所有按钮子项
        List<Long> buttonIds = authPermissionService.findIdsByParentIdAndType(
                menu.getId(),
                PermissionTypeEnum.BUTTON.getCode()
        );

        if (!buttonIds.isEmpty()) {
            // 删除按钮前先删除关联关系
            deleteRolePermissionsByPermissionIds(buttonIds);
            authPermissionService.batchMarkAsDeleted(buttonIds);
        }

        // 删除菜单关联关系
        deleteRolePermissionsByPermissionId(menu.getId());

        // 删除菜单本身
        return markAsDeleted(menu);
    }

    // 删除单个按钮
    private Boolean deleteButton(AuthPermission button) {
        // 删除按钮关联关系
        deleteRolePermissionsByPermissionId(button.getId());
        return markAsDeleted(button);
    }

    // 标记单个权限为已删除
    private Boolean markAsDeleted(AuthPermission permission) {
        permission.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        return authPermissionService.update(permission) != 0;
    }

    // 根据权限ID删除单个权限的关联关系
    private void deleteRolePermissionsByPermissionId(Long permissionId) {
        authRolePermissionService.deleteByPermissionId(permissionId);
    }

    // 批量删除权限ID列表的关联关系
    private void deleteRolePermissionsByPermissionIds(List<Long> permissionIds) {
        authRolePermissionService.batchDeleteByPermissionIds(permissionIds);
    }

    @Override
    public Boolean insert(AuthPermissionRequestVO requestVO) {
        AuthPermission entity = AuthPermissionConvert.INSTANCE.convert(requestVO);
        return authPermissionService.insert(entity) != 0;
    }

    @Override
    public AuthPermissionResponseVO get(Long id) {
        AuthPermission entity = authPermissionService.queryById(id);
        return AuthPermissionConvert.INSTANCE.convert(entity);
    }


    @Override
    public List<AuthPermissionResponseVO> getPermissionListByCurrentUser() {
        Long userId = getCurrentUserId();

        // 查询用户所有角色
        List<AuthUserRole> userRoles = authUserRoleService.queryByUserId(userId);
        if (userRoles.isEmpty()) {
            return Collections.emptyList();
        }

        // 提取角色ID并查询关联权限
        List<Long> roleIds = userRoles.stream()
                .map(AuthUserRole::getRoleId)
                .collect(Collectors.toList());
        List<AuthRolePermission> rolePermissions = authRolePermissionService.queryByRoleIds(roleIds);

        // 提取并去重权限ID
        List<Long> permissionIds = rolePermissions.stream()
                .map(AuthRolePermission::getPermissionId)
                .distinct()
                .collect(Collectors.toList());
        if (permissionIds.isEmpty()) {
            return Collections.emptyList();
        }

        // 批量查询权限并转换VO
        List<AuthPermission> permissions = authPermissionService.batchQueryByIds(permissionIds);
        return AuthPermissionConvert.INSTANCE.convertEntityToRespList(permissions);
    }

    @Override
    public List<AuthPermissionTreeVO> getPermissionTree() {
        // 查询所有有效权限
        List<AuthPermission> permissions = authPermissionService.selectAllPermissions();

        // 转换为TreeVO结构
        List<AuthPermissionTreeVO> treeNodes = permissions.stream()
                .map(AuthPermissionConvert.INSTANCE::convertToTreeVO)
                .collect(Collectors.toList());

        // 构建树形结构
        return buildPermissionTree(treeNodes);
    }

    /**
     * 构建权限树形结构
     *
     * @param nodes
     * @return
     */
    private List<AuthPermissionTreeVO> buildPermissionTree(List<AuthPermissionTreeVO> nodes) {
        Map<Long, AuthPermissionTreeVO> nodeMap = new LinkedHashMap<>();
        List<AuthPermissionTreeVO> rootNodes = new ArrayList<>();

        // 创建节点映射
        nodes.forEach(node -> {
            nodeMap.put(node.getId(), node);
            if (node.getParentId() == null || node.getParentId().equals(0L)) {
                rootNodes.add(node);
            }
        });

        // 构建父子关系
        nodes.forEach(node -> {
            if (node.getParentId() != null && node.getParentId() != 0L) {
                AuthPermissionTreeVO parent = nodeMap.get(node.getParentId());
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        });

        return rootNodes;
    }

    private Long getCurrentUserId() {
        String userIdStr = LoginContextHolder.getLoginId();
        if (StringUtils.isBlank(userIdStr)) {
            throw exception(ErrorCodeConstants.AUTH_USER_NOT_LOGIN);
        }
        try {
            return Long.parseLong(userIdStr);
        } catch (NumberFormatException e) {
            throw exception(ErrorCodeConstants.INVALID_USER_ID, userIdStr);
        }
    }
}
